package cn.keniykey.mc.viewlibrary.reflection;

import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.bukkit.Bukkit;
import org.bukkit.Server;

import cn.keniykey.mc.viewlibrary.ViewLibraryMain;

public final class ReflectionUtil {
	private ReflectionUtil() {
		throw new RuntimeException();
	}
	
	private static HashMap<String,String> hashmap_nmsname = new HashMap<>();
//	private static HashMap<String,Class<?>> hashmap_class_cache = new HashMap<>();
	private static boolean bool_spigot_server, bool_paper_server, bool_forge_server;
	private static String str_ver;
	
	static {
		hashmap_nmsname.put("nm", "net.minecraft");
		final Server server = Bukkit.getServer();
		final Pattern patter_package =  Pattern.compile("v\\d_\\d+_R\\d");
		Matcher matcher = patter_package.matcher(server.getClass().getPackage().getName());
		if(matcher.find()) hashmap_nmsname.put("cb", "org.bukkit.craftbukkit." + matcher.group());
		try {
            final Method getHandle = server.getClass().getDeclaredMethod("getHandle");
            final Object handle = getHandle.invoke(server);
            final Class<?> handle_serverclass = handle.getClass();
            matcher = patter_package.matcher(handle_serverclass.getPackage().getName());
            if(matcher.find()) hashmap_nmsname.put("nms", "net.minecraft.server." + matcher.group());
		}catch (Exception ex) {
			//ex.printStackTrace();
			ViewLibraryMain.getPlugin().getLogger().info("检测到运行在Forge服务端或Fabric服务端下");
			bool_forge_server = true;
		}
		try {
			Bukkit.class.getMethod("spigot");
			bool_spigot_server = true;
		}catch(Exception ex) {}
		try {
			Class.forName("com.destroystokyo.paper.PaperCommand");
			bool_paper_server = true;
		}catch(Exception ex) {}
		
		matcher = Pattern.compile("\\d+\\.\\d+(\\.\\d+)?").matcher(Bukkit.getServer().getVersion());
		str_ver = matcher.find() ? matcher.group() : "1.16.5";
	}
	public static boolean isSpigotServer() {
		return bool_spigot_server;
	}
	public static boolean isPaperServer() {
		return bool_paper_server;
	}
	public static boolean isForgeServer() {
		return bool_forge_server;
	}
	public static String getMinecraftVersion() {
		return str_ver;
	}
	/**
	 * nms：net.minecraft.server.xxx.
	 * cb：org.bukkit.craftbukkit.xxx.
	 * nm：net.minecraft.
	 * @param pattern 例如："nms,NBTTagCompound","NBTTagCompound" = "net.minecraft.server.xxx.NBTTagCompound","NBTTagCompound" 
	 */
	public static ReflectionClass findReflectionClass(final String... pattern) {
		return new ReflectionClass(findClass(pattern));
	}
	public static Class<?> findClass(final String... pattern) {
		LinkedList<String> notfoundclasses = null;
		for(final String name : pattern) {
			if (name.isEmpty()) continue;
			final String pattern_name = checkPackageName(name);
			try {
				final Class<?> clazz = Class.forName(pattern_name);
				if (clazz != null) {
//					hashmap_class_cache.put(clazz.getName(), clazz);
					return clazz;
				}
			}catch(ClassNotFoundException ex) {
				if(notfoundclasses == null) notfoundclasses = new LinkedList<>();
				notfoundclasses.add(pattern_name);
			}
		}
		final StringBuilder builder = new StringBuilder("can not find the class(ClassNotFoundException)(找不到Class类): ");
		for(final String classname : pattern) {
			builder.append(classname);
			builder.append(", ");
		}
		throw new RuntimeException(builder.substring(0, builder.length()-2));
	}
	private static String checkPackageName(String pattern) {
		final String[] package_names = pattern.split(",");
		if(package_names.length == 1) return pattern;
		final StringBuilder builder = new StringBuilder(hashmap_nmsname.containsKey(package_names[0]) ? hashmap_nmsname.get(package_names[0]) :
			package_names[0]);
		builder.append('.').append(package_names[1]);
		return builder.toString();
	}
}